home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / olecon~1 / framewrk / autoobj.cpp next >
Encoding:
C/C++ Source or Header  |  1995-11-25  |  14.0 KB  |  471 lines

  1. //=--------------------------------------------------------------------------=
  2. // AutomationObject.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // all of our objects will inherit from this class to share as much of the same
  13. // code as possible.  this super-class contains the unknown, dispatch and
  14. // error info implementations for them.
  15. //
  16. #include "IPServer.H"
  17. #include "LocalSrv.H"
  18.  
  19. #include "AutoObj.H"
  20. #include "Globals.H"
  21. #include "Util.H"
  22.  
  23.  
  24. SZTHISFILE
  25.  
  26.  
  27. //=--------------------------------------------------------------------------=
  28. // CAutomationObject::CAutomationObject
  29. //=--------------------------------------------------------------------------=
  30. // create the object and initialize the refcount
  31. //
  32. // Parameters:
  33. //    IUnknown *      - [in] controlling Unknown
  34. //    int             - [in] the object type that we are
  35. //    void *          - [in] the VTable of of the object we really are.
  36. //
  37. // Notes:
  38. //
  39. CAutomationObject::CAutomationObject 
  40. (
  41.     IUnknown *pUnkOuter,
  42.     int   ObjType,
  43.     void *pVTable
  44. )
  45. : CUnknownObject(pUnkOuter, pVTable), m_ObjectType (ObjType)
  46. {
  47.     m_fLoadedTypeInfo = FALSE;
  48. }
  49.  
  50.  
  51. //=--------------------------------------------------------------------------=
  52. // CAutomationObject::~CAutomationObject
  53. //=--------------------------------------------------------------------------=
  54. // "I have a rendezvous with Death, At some disputed barricade"
  55. // - Alan Seeger (1888-1916)
  56. //
  57. // Notes:
  58. //
  59. CAutomationObject::~CAutomationObject ()
  60. {
  61.     // if we loaded up a type info, release our count on the globally stashed
  62.     // type infos, and release if it becomes zero.
  63.     //
  64.     if (m_fLoadedTypeInfo) {
  65.         ASSERT(CTYPEINFOOFOBJECT(m_ObjectType), "Bogus ref counting on the Type Infos");
  66.         CTYPEINFOOFOBJECT(m_ObjectType)--;
  67.  
  68.         // if we're the last one, free that sucker!
  69.         //
  70.         if (!CTYPEINFOOFOBJECT(m_ObjectType)) {
  71.             PTYPEINFOOFOBJECT(m_ObjectType)->Release();
  72.             PTYPEINFOOFOBJECT(m_ObjectType) = NULL;
  73.         }
  74.     }
  75.  
  76.     return;
  77. }
  78.  
  79. //=--------------------------------------------------------------------------=
  80. // CAutomationObject::InternalQueryInterface
  81. //=--------------------------------------------------------------------------=
  82. // the controlling unknown will call this for us in the case where they're
  83. // looking for a specific interface.
  84. //
  85. // Parameters:
  86. //    REFIID        - [in]  interface they want
  87. //    void **       - [out] where they want to put the resulting object ptr.
  88. //
  89. // Output:
  90. //    HRESULT       - S_OK, E_NOINTERFACE
  91. //
  92. // Notes:
  93. //
  94. HRESULT CAutomationObject::InternalQueryInterface
  95. (
  96.     REFIID riid,
  97.     void **ppvObjOut
  98. )
  99. {
  100.     ASSERT(ppvObjOut, "controlling Unknown should be checking this!");
  101.  
  102.     // start looking for the guids we support, namely IDispatch, and the
  103.     //
  104.     if (DO_GUIDS_MATCH(riid, IID_IDispatch)) {
  105.         *ppvObjOut = (void *)(IDispatch *)m_pvInterface;
  106.         ((IUnknown *)(*ppvObjOut))->AddRef();
  107.         return S_OK;
  108.     }
  109.  
  110.     // just get our parent class to process it from here on out.
  111.     //
  112.     return CUnknownObject::InternalQueryInterface(riid, ppvObjOut);
  113. }
  114.  
  115. //=--------------------------------------------------------------------------=
  116. // CAutomationObject::GetTypeInfoCount
  117. //=--------------------------------------------------------------------------=
  118. // returns the number of type information interfaces that the object provides
  119. //
  120. // Parameters:
  121. //    UINT *            - [out] the number of interfaces supported.
  122. //
  123. // Output:
  124. //    HRESULT           - S_OK, E_NOTIMPL, E_INVALIDARG
  125. //
  126. // Notes:
  127. //
  128. STDMETHODIMP CAutomationObject::GetTypeInfoCount
  129. (
  130.     UINT *pctinfo
  131. )
  132. {
  133.     // arg checking
  134.     //
  135.     if (!pctinfo)
  136.         return E_INVALIDARG;
  137.  
  138.     // we support GetTypeInfo, so we need to return the count here.
  139.     //
  140.     *pctinfo = 1;
  141.     return S_OK;
  142. }
  143.  
  144. //=--------------------------------------------------------------------------=
  145. // CAutomationObject::GetTypeInfo
  146. //=--------------------------------------------------------------------------=
  147. // Retrieves a type information object, which can be used to get the type
  148. // information for an interface.
  149. //
  150. // Parameters:
  151. //    UINT              - [in]  the type information they'll want returned
  152. //    LCID              - [in]  the LCID of the type info we want
  153. //    ITypeInfo **      - [out] the new type info object.
  154. //
  155. // Output:
  156. //    HRESULT           - S_OK, E_INVALIDARG, etc.
  157. //
  158. // Notes:
  159. //
  160. STDMETHODIMP CAutomationObject::GetTypeInfo
  161. (
  162.     UINT        itinfo,
  163.     LCID        lcid,
  164.     ITypeInfo **ppTypeInfoOut
  165. )
  166. {
  167.     DWORD       dwPathLen;
  168.     char        szDllPath[MAX_PATH];
  169.     HRESULT     hr;
  170.     ITypeLib   *pTypeLib;
  171.     ITypeInfo **ppTypeInfo =NULL;
  172.  
  173.     // arg checking
  174.     //
  175.     if (itinfo != 0)
  176.         return DISP_E_BADINDEX;
  177.  
  178.     if (!ppTypeInfoOut)
  179.         return E_POINTER;
  180.  
  181.     *ppTypeInfoOut = NULL;
  182.  
  183.     // ppTypeInfo will point to our global holder for this particular
  184.     // type info.  if it's null, then we have to load it up. if it's not
  185.     // NULL, then it's already loaded, and we're happy.
  186.     //
  187.     ppTypeInfo = PPTYPEINFOOFOBJECT(m_ObjectType);
  188.  
  189.     if (*ppTypeInfo == NULL) {
  190.  
  191.         ITypeInfo *pTypeInfoTmp;
  192.         HREFTYPE   hrefType;
  193.  
  194.         // we don't have the type info around, so go load the sucker.
  195.         //
  196.         hr = LoadRegTypeLib(*g_pLibid, (USHORT)VERSIONOFOBJECT(m_ObjectType), 0,
  197.                             LANGIDFROMLCID(g_lcidLocale), &pTypeLib);
  198.  
  199.         // if, for some reason, we failed to load the type library this
  200.         // way, we're going to try and load the type library directly out of
  201.         // our resources.  this has the advantage of going and re-setting all
  202.         // the registry information again for us.
  203.         //
  204.         if (FAILED(hr)) {
  205.  
  206.             dwPathLen = GetModuleFileName(GetResourceHandle(), szDllPath, MAX_PATH);
  207.             if (!dwPathLen)
  208.                 return E_FAIL;
  209.  
  210.             MAKE_WIDEPTR_FROMANSI(pwsz, szDllPath);
  211.             hr = LoadTypeLib(pwsz, &pTypeLib);
  212.             RETURN_ON_FAILURE(hr);
  213.         }
  214.  
  215.         // we've got the Type Library now, so get the type info for the interface
  216.         // we're interested in.
  217.         //
  218.         hr = pTypeLib->GetTypeInfoOfGuid((REFIID)INTERFACEOFOBJECT(m_ObjectType), &pTypeInfoTmp);
  219.         pTypeLib->Release();
  220.         RETURN_ON_FAILURE(hr);
  221.  
  222.         hr = pTypeInfoTmp->GetRefTypeOfImplType(0xffffffff, &hrefType);
  223.         if (FAILED(hr)) {
  224.             pTypeInfoTmp->Release();
  225.             return hr;
  226.         }
  227.  
  228.         hr = pTypeInfoTmp->GetRefTypeInfo(hrefType, ppTypeInfo);
  229.         pTypeInfoTmp->Release();
  230.         RETURN_ON_FAILURE(hr);
  231.  
  232.         // add an extra reference to this object.  if it ever becomes zero, then
  233.         // we need to release it ourselves.
  234.         //
  235.         CTYPEINFOOFOBJECT(m_ObjectType)++;
  236.         m_fLoadedTypeInfo = TRUE;
  237.     }
  238.  
  239.  
  240.     // we still have to go and addref the Type info object, however, so that
  241.     // the people using it can release it.
  242.     //
  243.     (*ppTypeInfo)->AddRef();
  244.     *ppTypeInfoOut = *ppTypeInfo;
  245.  
  246.     return S_OK;
  247. }
  248.  
  249.  
  250.  
  251. //=--------------------------------------------------------------------------=
  252. // CAutomationObject::GetIDsOfNames
  253. //=--------------------------------------------------------------------------=
  254. // Maps a single member and an optional set of argument names to a
  255. // corresponding set of integer DISPIDs
  256. //
  257. // Parameters:
  258. //    REFIID            - [in]  must be IID_NULL
  259. //    OLECHAR **        - [in]  array of names to map.
  260. //    UINT              - [in]  count of names in the array.
  261. //    LCID              - [in]  LCID on which to operate
  262. //    DISPID *          - [in]  place to put the corresponding DISPIDs.
  263. //
  264. // Output:
  265. //    HRESULT           - S_OK, E_OUTOFMEMORY, DISP_E_UNKNOWNNAME,
  266. //                        DISP_E_UNKNOWNLCID
  267. //
  268. // Notes:
  269. //    - we're just going to use DispGetIDsOfNames to save us a lot of hassle,
  270. //      and to let this superclass handle it.
  271. //
  272. STDMETHODIMP CAutomationObject::GetIDsOfNames
  273. (
  274.     REFIID    riid,
  275.     OLECHAR **rgszNames,
  276.     UINT      cNames,
  277.     LCID      lcid,
  278.     DISPID   *rgdispid
  279. )
  280. {
  281.     HRESULT     hr;
  282.     ITypeInfo  *pTypeInfo;
  283.  
  284.     if (!DO_GUIDS_MATCH(riid, IID_NULL))
  285.         return E_INVALIDARG;
  286.  
  287.     // get the type info for this dude!
  288.     //
  289.     hr = GetTypeInfo(0, lcid, &pTypeInfo);
  290.     RETURN_ON_FAILURE(hr);
  291.  
  292.     // use the standard provided routines to do all the work for us.
  293.     //
  294.     hr = pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  295.     pTypeInfo->Release();
  296.  
  297.     return hr;
  298. }
  299.  
  300. //=--------------------------------------------------------------------------=
  301. // CAutomationObject::Invoke
  302. //=--------------------------------------------------------------------------=
  303. // provides access to the properties and methods on this object.
  304. //
  305. // Parameters:
  306. //    DISPID            - [in]  identifies the member we're working with.
  307. //    REFIID            - [in]  must be IID_NULL.
  308. //    LCID              - [in]  language we're working under
  309. //    USHORT            - [in]  flags, propput, get, method, etc ...
  310. //    DISPPARAMS *      - [in]  array of arguments.
  311. //    VARIANT *         - [out] where to put result, or NULL if they don't care.
  312. //    EXCEPINFO *       - [out] filled in in case of exception
  313. //    UINT *            - [out] where the first argument with an error is.
  314. //
  315. // Output:
  316. //    HRESULT           - tonnes of them.
  317. //
  318. // Notes:
  319. //    
  320. STDMETHODIMP CAutomationObject::Invoke
  321. (
  322.     DISPID      dispid,
  323.     REFIID      riid,
  324.     LCID        lcid,
  325.     WORD        wFlags,
  326.     DISPPARAMS *pdispparams,
  327.     VARIANT    *pvarResult,
  328.     EXCEPINFO  *pexcepinfo,
  329.     UINT       *puArgErr
  330. )
  331. {
  332.     HRESULT    hr;
  333.     ITypeInfo *pTypeInfo;
  334.  
  335.     if (!DO_GUIDS_MATCH(riid, IID_NULL))
  336.         return E_INVALIDARG;
  337.  
  338.     // get our typeinfo first!
  339.     //
  340.     hr = GetTypeInfo(0, lcid, &pTypeInfo);
  341.     RETURN_ON_FAILURE(hr);
  342.  
  343.     // Clear exceptions
  344.     //
  345.     SetErrorInfo(0L, NULL);
  346.  
  347.     // This is exactly what DispInvoke does--so skip the overhead.
  348.     //
  349.     hr = pTypeInfo->Invoke(m_pvInterface, dispid, wFlags,
  350.                            pdispparams, pvarResult,
  351.                            pexcepinfo, puArgErr);
  352.     pTypeInfo->Release();
  353.     return hr;
  354.  
  355. }
  356.  
  357. //=--------------------------------------------------------------------------=
  358. // CAutomationObject::Exception
  359. //=--------------------------------------------------------------------------=
  360. // fills in the rich error info object so that both our vtable bound interfaces
  361. // and calls through ITypeInfo::Invoke get the right error informaiton.
  362. //
  363. // Parameters:
  364. //    HRESULT          - [in] the SCODE that should be associated with this err
  365. //    WORD             - [in] the RESOURCE ID of the error message.
  366. //    DWORD            - [in] helpcontextid for the error
  367. //
  368. // Output:
  369. //    HRESULT          - the HRESULT that was passed in.
  370. //
  371. // Notes:
  372. //
  373. HRESULT CAutomationObject::Exception
  374. (
  375.     HRESULT hrExcep,
  376.     WORD    idException,
  377.     DWORD   dwHelpContextID
  378. )
  379. {
  380.     ICreateErrorInfo *pCreateErrorInfo;
  381.     IErrorInfo *pErrorInfo;
  382.     WCHAR   wszTmp[256];
  383.     char    szTmp[256];
  384.     HRESULT hr;
  385.  
  386.  
  387.     // first get the createerrorinfo object.
  388.     //
  389.     hr = CreateErrorInfo(&pCreateErrorInfo);
  390.     if (FAILED(hr)) return hrExcep;
  391.  
  392.     MAKE_WIDEPTR_FROMANSI(wszHelpFile, HELPFILEOFOBJECT(m_ObjectType));
  393.  
  394.     // set up some default information on it.
  395.     //
  396.     pCreateErrorInfo->SetGUID((REFIID)INTERFACEOFOBJECT(m_ObjectType));
  397.     pCreateErrorInfo->SetHelpFile(wszHelpFile);
  398.     pCreateErrorInfo->SetHelpContext(dwHelpContextID);
  399.  
  400.     // load in the actual error string value.  max of 256.
  401.     //
  402.     LoadString(GetResourceHandle(), idException, szTmp, 256);
  403.     MultiByteToWideChar(CP_ACP, 0, szTmp, -1, wszTmp, 256);
  404.     pCreateErrorInfo->SetDescription(wszTmp);
  405.  
  406.     // load in the source
  407.     //
  408.     MultiByteToWideChar(CP_ACP, 0, NAMEOFOBJECT(m_ObjectType), -1, wszTmp, 256);
  409.     pCreateErrorInfo->SetSource(wszTmp);
  410.  
  411.     // now set the Error info up with the system
  412.     //
  413.     hr = pCreateErrorInfo->QueryInterface(IID_IErrorInfo, (void **)&pErrorInfo);
  414.     CLEANUP_ON_FAILURE(hr);
  415.  
  416.     SetErrorInfo(0, pErrorInfo);
  417.     pErrorInfo->Release();
  418.  
  419.   CleanUp:
  420.     pCreateErrorInfo->Release();
  421.     return hrExcep;
  422. }
  423.  
  424. //=--------------------------------------------------------------------------=
  425. // CAutomationObject::InterfaceSupportsErrorInfo
  426. //=--------------------------------------------------------------------------=
  427. // indicates whether or not the given interface supports rich error information
  428. //
  429. // Parameters:
  430. //    REFIID        - [in] the interface we want the answer for.
  431. //
  432. // Output:
  433. //    HRESULT       - S_OK = Yes, S_FALSE = No.
  434. //
  435. // Notes:
  436. //
  437. HRESULT CAutomationObject::InterfaceSupportsErrorInfo
  438. (
  439.     REFIID riid
  440. )
  441. {
  442.     // see if it's the interface for the type of object that we are.
  443.     //
  444.     if (riid == (REFIID)INTERFACEOFOBJECT(m_ObjectType))
  445.         return S_OK;
  446.  
  447.     return S_FALSE;
  448. }
  449.  
  450. //=--------------------------------------------------------------------------=
  451. // CAutomationObject::GetResourceHandle    [helper]
  452. //=--------------------------------------------------------------------------=
  453. // virtual routine to get the resource handle.  virtual, so that inheriting
  454. // objects, such as COleControl can use theirs instead, which goes and gets
  455. // the Host's version ...
  456. //
  457. // Output:
  458. //    HINSTANCE
  459. //
  460. // Notes:
  461. //
  462. HINSTANCE CAutomationObject::GetResourceHandle
  463. (
  464.     void
  465. )
  466. {
  467.     return ::GetResourceHandle();
  468. }
  469.  
  470.  
  471.